package com.lzx.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzx.common.utils.*;
import com.lzx.user.entity.User;
import com.lzx.user.entity.vo.*;
import com.lzx.user.feign.ArticleClient;
import com.lzx.user.feign.AnswerClient;
import com.lzx.user.feign.dto.*;
import com.lzx.user.mapper.UserMapper;
import com.lzx.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lzx
 * @since 2022-10-03
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private AnswerClient problemClient;

    @Resource
    private ArticleClient articleClient;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    //登录
    @Override
    public R login(User user, HttpServletRequest request) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile", user.getMobile());
        User vo = userMapper.selectOne(wrapper);
        if (vo == null) {
            return R.error().message("手机号不存在");
        }
        //密码匹对
        boolean flag = encoder.matches(user.getPassword(), vo.getPassword());
        if (flag) {
            vo.setIp(IpUtils.getIpAddress(request));
            vo.setAddress(AddressUtils.getCityInfo(IpUtils.getIpAddress(request)));
            userMapper.updateById(vo);
            //redis中存在token
            if (stringRedisTemplate.opsForValue().get("ordinary:" + user.getMobile() + ":token") != null) {
                return R.ok().data("token", stringRedisTemplate.opsForValue().get("ordinary:" + user.getMobile() + ":token"));
            }
            //redis中不存在token，则重新生成token
            String token = JwtUtils.getJwtToken(String.valueOf(vo.getId()), vo.getMobile());
            stringRedisTemplate.opsForValue().set("ordinary:" + user.getMobile() + ":token", token, 2, TimeUnit.HOURS);
            return R.ok().data("token", token);
        } else {
            return R.error().message("密码错误");
        }
    }

    //判断手机号是否已经注册
    @Override
    public R mobileIsRegister(String mobile) {
        User user = userMapper.selectByMobile(mobile);
        if (user != null) {
            return R.error().message("手机号已注册!");
        } else {
            return R.ok();
        }
    }

    //注册
    @Override
    public R register(User user) {
        //密码加密
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        User vo = new User();
        vo.setPassword(encoder.encode(user.getPassword()));
        vo.setMobile(user.getMobile());
        vo.setCreateTime(new Date());
        vo.setNickname("fiveCube" + user.getMobile());
        vo.setAvatar("https://five-cube.oss-cn-beijing.aliyuncs.com/userPhoto/dog.jpg");
        //根据手机号来查询
        User flagByMobile = userMapper.selectByMobile(user.getMobile());
        //校验验证码是否正确
        String code = stringRedisTemplate.opsForValue().get("fiveCube:sms:code:" + user.getMobile());
        if (flagByMobile != null) {
            return R.error().message("手机号已存在");
        } else if (user.getCode() == null) {
            return R.error().message("验证码不能为空");
        } else if (!Objects.equals(code, user.getCode())) {
            return R.error().message("验证码错误");
        } else if (user.getCode() != null && Objects.equals(code, user.getCode())) {
            userMapper.insert(vo);
            return R.ok().message("注册成功");
        } else {
            return R.error().message("注册失败");
        }
    }

    //更新用户头像
    @Transactional
    @Override
    public R updateAvatar(OssVO ossVO) {
        User user = userMapper.selectById(ossVO.getId());
        String avatar = user.getAvatar();
        user.setAvatar(ossVO.getAvatar());
        userMapper.updateById(user);
        //使用MQ来发送延迟消息 修改用户头像
        rocketMQTemplate.syncSend("avatar-edit-topic", MessageBuilder.withPayload(ossVO).build(), 3600000, 4);
        return R.ok().message(avatar);
    }

    //根据token获取个人信息
    @Override
    public R getUserInfo(HttpServletRequest request) {
        String s;
        User user;
        //判断请求头中是否携带token
        if (request.getHeader("token") != null) {
            //校验token是否有效
            if (JwtUtils.checkToken(request.getHeader("token"))) {
                //获取用户id
                String id = JwtUtils.getMemberIdByJwtToken(request);
                user = userMapper.selectById(id);
                //判断token是否过期
                s = stringRedisTemplate.opsForValue().get("ordinary:" + user.getMobile() + ":token");
            } else {
                return R.error().message("token过期了");
            }
        } else {
            return R.error().message("token不存在!");
        }
        if (s == null) {
            log.info("token过期了");
            return R.error().message("token过期了");
        }
        return R.ok().data("user", user);
    }

    //用户点赞问题，用户积分+1
    @Transactional
    @Override
    public R likeProblem(Integer userId) {
        User user = userMapper.selectById(userId);
        user.setIntegral(user.getIntegral() + 1);
        userMapper.updateById(user);
        return R.ok().message("用户积分+1");
    }

    //根据id获取用户信息
    @Override
    public R getUserinfoById(Long id) {
        User user = userMapper.selectById(id);
        return R.ok().data("user", user);
    }

    //用户回答问题，回答数+1
    @Transactional
    @Override
    public R userReplyAdd(Long userId) {
        User user = userMapper.selectById(userId);
        user.setReplyCount(user.getReplyCount() + 1);
        userMapper.updateById(user);
        return R.ok().message("增加成功");
    }

    //根据用户回答数查询前十个用户
    @Override
    public R rankBeforeTen() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("reply_count").last("limit 10");
        List<User> list = userMapper.selectList(wrapper);
        return R.ok().data("list", list);
    }

    //获取所有用户
    @Override
    public R getList() {
        List<User> list = userMapper.selectList(null);
        return R.ok().data("list", list);
    }

    //用户修改信息(前台)
    @Override
    public R updateUserinfo(UserinfoVO userinfoVO) {
        User user = userMapper.selectById(userinfoVO.getId());
        user.setUpdateTime(new Date());
        if (!Objects.equals(user.getMobile(), userinfoVO.getMobile())) {
            //通过手机号来查询用户
            User user1 = userMapper.selectByMobile(userinfoVO.getMobile());
            if (user1 != null) {
                return R.error().message("手机号已经存在");
            } else if (!Objects.equals(user.getNickname(), userinfoVO.getNickname())) {
                //通过昵称来查询用户
                User user2 = userMapper.selectByNickname(userinfoVO.getNickname());
                if (user2 != null) {
                    return R.error().message("昵称已经存在");
                } else {
                    BeanUtils.copyProperties(userinfoVO, user);
                    userMapper.updateById(user);
                    //使用MQ来发送延迟消息 修改用户昵称
                    NicknameVO nicknameVO = new NicknameVO();
                    nicknameVO.setId(user.getId());
                    nicknameVO.setNickname(userinfoVO.getNickname());
                    rocketMQTemplate.syncSend("nickname-edit-topic", MessageBuilder.withPayload(nicknameVO).build(), 3600000, 4);
                    return R.ok().message("修改成功");
                }
            } else {
                BeanUtils.copyProperties(userinfoVO, user);
                userMapper.updateById(user);
                return R.ok().message("修改成功");
            }
        } else if (!Objects.equals(user.getNickname(), userinfoVO.getNickname())) {
            //通过昵称来查询用户
            User user2 = userMapper.selectByNickname(userinfoVO.getNickname());
            if (user2 != null) {
                return R.error().message("昵称已经存在");
            } else if (!Objects.equals(user.getMobile(), userinfoVO.getMobile())) {
                //通过手机号来查询用户
                User user1 = userMapper.selectByMobile(userinfoVO.getMobile());
                if (user1 != null) {
                    return R.error().message("手机号已经存在");
                } else {
                    BeanUtils.copyProperties(userinfoVO, user);
                    userMapper.updateById(user);
                    //使用MQ来发送延迟消息 修改用户昵称
                    NicknameVO nicknameVO = new NicknameVO();
                    nicknameVO.setId(user.getId());
                    nicknameVO.setNickname(userinfoVO.getNickname());
                    rocketMQTemplate.syncSend("nickname-edit-topic", MessageBuilder.withPayload(nicknameVO).build(), 3600000, 4);
                    return R.ok().message("修改成功");
                }
            } else {
                BeanUtils.copyProperties(userinfoVO, user);
                userMapper.updateById(user);
                //使用MQ来发送延迟消息 修改用户昵称
                NicknameVO nicknameVO = new NicknameVO();
                nicknameVO.setId(user.getId());
                nicknameVO.setNickname(userinfoVO.getNickname());
                rocketMQTemplate.syncSend("nickname-edit-topic", MessageBuilder.withPayload(nicknameVO).build(), 3600000, 4);
                return R.ok().message("修改成功");
            }
        } else {
            BeanUtils.copyProperties(userinfoVO, user);
            userMapper.updateById(user);
            return R.ok().message("修改成功");
        }
    }

    //用户关注其他人，关注数+1，被关注的人粉丝数+1；取消关注其他人，关注数-1，被关注的人粉丝数-1
    @Transactional
    @Override
    public R attentionAndCancelAttention(Long userId, Integer isAttention, Long attentionUserId) {
        User user = userMapper.selectById(userId);
        User attentionUser = userMapper.selectById(attentionUserId);
        if (isAttention == 0) {
            user.setAttentionCount(user.getAttentionCount() + 1);
            userMapper.updateById(user);
            attentionUser.setFansCount(attentionUser.getFansCount() + 1);
            userMapper.updateById(attentionUser);
            return R.ok().message("关注成功");
        } else {
            user.setAttentionCount(user.getAttentionCount() - 1);
            userMapper.updateById(user);
            attentionUser.setFansCount(attentionUser.getFansCount() - 1);
            userMapper.updateById(attentionUser);
            return R.ok().message("取消关注成功");
        }
    }

    //获取所有用户
    @Override
    public R getUserList(int current, int size) {
        List<User> userList = userMapper.getUserList();
        //总数量
        int total = userList.size();
        if (size > total) {
            size = total;
        }
        // 求出最大页数，防止currentPage越界
        int maxPage = total % size == 0 ? total / size : total / size + 1;
        if (current > maxPage) {
            current = maxPage;
        }
        // 当前页第一条数据的下标
        int curIdx = current > 1 ? (current - 1) * size : 0;
        List<User> pageList = new ArrayList<>();
        // 将当前页的数据放进pageList
        for (int i = 0; i < size && curIdx + i < total; i++) {
            pageList.add(userList.get(curIdx + i));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("list", pageList);
        map.put("total", total);
        return R.ok().data("map", map);
    }

    //新增用户
    @Override
    public R addUser(User user) {
        //通过手机号来查询用户
        User user1 = userMapper.selectByMobile(user.getMobile());
        if (user1 != null) {
            return R.error().message("手机号已经存在");
        }
        //通过昵称来查询用户
        User user2 = userMapper.selectByNickname(user.getNickname());
        if (user2 != null) {
            return R.error().message("昵称已经存在");
        }
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        user.setPassword(encoder.encode(user.getPassword()));
        user.setAvatar("https://five-cube.oss-cn-beijing.aliyuncs.com/userPhoto/dog.jpg");
        user.setCreateTime(new Date());
        userMapper.insert(user);
        return R.ok().message("新增成功");
    }

    //修改用户信息(后台)
    @Override
    public R updateUser(UserVO userVO) {
        User user = userMapper.selectById(userVO.getId());
        userVO.setUpdateTime(new Date());
        if (!Objects.equals(user.getMobile(), userVO.getMobile())) {
            //通过手机号来查询用户
            User user1 = userMapper.selectByMobile(userVO.getMobile());
            if (user1 != null) {
                return R.error().message("手机号已经存在");
            } else if (!Objects.equals(user.getNickname(), userVO.getNickname())) {
                //通过昵称来查询用户
                User user2 = userMapper.selectByNickname(userVO.getNickname());
                if (user2 != null) {
                    return R.error().message("昵称已经存在");
                } else {
                    BeanUtils.copyProperties(userVO, user);
                    userMapper.updateById(user);
                    return R.ok().message("修改成功");
                }
            } else {
                BeanUtils.copyProperties(userVO, user);
                userMapper.updateById(user);
                return R.ok().message("修改成功");
            }
        } else if (!Objects.equals(user.getNickname(), userVO.getNickname())) {
            //通过昵称来查询用户
            User user2 = userMapper.selectByNickname(userVO.getNickname());
            if (user2 != null) {
                return R.error().message("昵称已经存在");
            } else if (!Objects.equals(user.getMobile(), userVO.getMobile())) {
                //通过手机号来查询用户
                User user1 = userMapper.selectByMobile(userVO.getMobile());
                if (user1 != null) {
                    return R.error().message("手机号已经存在");
                } else {
                    BeanUtils.copyProperties(userVO, user);
                    userMapper.updateById(user);
                    return R.ok().message("修改成功");
                }
            } else {
                BeanUtils.copyProperties(userVO, user);
                userMapper.updateById(user);
                return R.ok().message("修改成功");
            }
        } else {
            BeanUtils.copyProperties(userVO, user);
            userMapper.updateById(user);
            return R.ok().message("修改成功");
        }
    }

    //禁用用户
    @Override
    public R deleteUser(List<Long> ids) {
        userMapper.deleteBatchIds(ids);
        return R.ok().message("禁用成功!");
    }

    //解禁用户
    @Override
    public R relieveUser(Long id) {
        User user = userMapper.selectUserById(id);
        user.setStatus("0");
        userMapper.updateUserById(id);
        return R.ok().message("解禁成功!");
    }

    //根据id获取用户信息
    @Override
    public R getUser(Long id) {
        User user = userMapper.selectUserById(id);
        return R.ok().data("user", user);
    }

    //搜索
    @Override
    public R searchUser(SearchParams searchParams) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StringUtils.isNoneBlank(searchParams.getMobile())) {
            wrapper.like("mobile", searchParams.getMobile());
        }
        if (StringUtils.isNoneBlank(searchParams.getNickname())) {
            wrapper.like("nickname", searchParams.getNickname());
        }
        if (StringUtils.isNoneBlank(searchParams.getSex())) {
            wrapper.eq("sex", searchParams.getSex());
        }
        if (StringUtils.isNoneBlank(searchParams.getEmail())) {
            wrapper.like("email", searchParams.getEmail());
        }
        if (searchParams.getMinIntegral() != null) {
            wrapper.ge("integral", searchParams.getMinIntegral());
        }
        if (searchParams.getMaxIntegral() != null) {
            wrapper.le("integral", searchParams.getMaxIntegral());
        }
        List<User> list = userMapper.selectList(wrapper);
        return R.ok().data("list", list);
    }

    //导出
    @Override
    public void exportUser(HttpServletResponse response) {
        List<User> userList = userMapper.selectList(null);
        ExcelUtils.export(response, "用户信息", User.class, userList);
    }

    //获取所有用户昵称
    @Override
    public R getUserNickname() {
        List<User> userList = userMapper.selectList(null);
        List<String> list = userList.stream().map((User::getNickname)).collect(Collectors.toList());
        return R.ok().data("list", list);
    }

    //获取回答数前十的用户(不包括当前登录用户)
    @Override
    public List<User> getUserByReplyCount(int userId) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.ne("id", userId).orderByDesc("reply_count").last("limit 10");
        return userMapper.selectList(wrapper);
    }

    //获取所有用户id
    @Override
    public List<Long> getUserIdList() {
        List<User> userList = userMapper.selectList(null);
        List<Long> list = new ArrayList<>();
        userList.forEach(user -> list.add(user.getId()));
        return list;
    }

    //获取用户浏览记录
    @Override
    public R getUserBrowseList(Long userId) {
        ArrayList<BrowseVO> browseVOS = new ArrayList<>();
        //获取问题浏览记录
        List<ProblemBrowseVO> browseProblem = problemClient.getProblemBrowseListToUser(userId);
        for (ProblemBrowseVO problemBrowseVO : browseProblem) {
            BrowseVO<Problem> problemBrowseVOBrowseVO = new BrowseVO<>();
            BeanUtils.copyProperties(problemBrowseVO, problemBrowseVOBrowseVO);
            problemBrowseVOBrowseVO.setT(problemBrowseVO.getProblem());
            problemBrowseVOBrowseVO.setTId(2);
            browseVOS.add(problemBrowseVOBrowseVO);
        }
        List<ArticleBrowseVO> browseArticle = articleClient.getArticleBrowseListToUser(userId);
        for (ArticleBrowseVO articleBrowseVO : browseArticle) {
            BrowseVO<Articles> articlesBrowseVO = new BrowseVO<>();
            BeanUtils.copyProperties(articleBrowseVO, articlesBrowseVO);
            articleBrowseVO.getArticles().setLabels(Arrays.asList(articleBrowseVO.getArticles().getLabelTranslation().split(",")));
            articlesBrowseVO.setT(articleBrowseVO.getArticles());
            articlesBrowseVO.setTId(1);
            browseVOS.add(articlesBrowseVO);
        }
        browseVOS.sort((t1, t2) -> t2.getBrowseTime().compareTo(t1.getBrowseTime()));
        return R.ok().data("list", browseVOS);
    }
}
